﻿/// Copyright © 2013 Microsoft Corporation. 
/// This project is released under the Microsoft Public License (MS-PL)
///
namespace DataMorph.Generator
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Text;
    using System.Threading;

    using DataMorph.Common.Contracts;

    public class TagDataGenerator : ITagDataGenerator
    {
        private const int IntegerMinValue = 0;

        private const int IntegerMaxValue = 999;

        private const int TextValueLength = 1000;

        private const int TextValuesPoolCapacity = 2000;

        private static readonly ThreadLocal<Random> Random = new ThreadLocal<Random>(() => new Random());

        private readonly IList<string> textValuesPool = new List<string>();

        public TagDataGenerator()
        {
            this.textValuesPool = new List<string>(TextValuesPoolCapacity);
            for (int i = 0; i < TextValuesPoolCapacity; i++)
            {
                this.textValuesPool.Add(this.GenerateTextValue(TextValueLength));
            }
        }

        public TagData Generate(Tag tag, DateTime dateTime)
        {
            return new TagData
            {
                TagId = tag.Id,
                Ticks = dateTime.Ticks,
                Value = this.GenerateValue(tag.Type)
            };
        }

        public TagData Generate(Tag tag)
        {
            return new TagData
            {
                TagId = tag.Id,
                Value = this.GenerateValue(tag.Type)
            };
        }

        private string GenerateValue(TagType type)
        {
            switch (type)
            {
                case TagType.Bit:
                    return this.GenerateBitValue().ToString(CultureInfo.InvariantCulture);

                case TagType.Integer:
                    return this.GenerateIntegerValue(IntegerMinValue, IntegerMaxValue).ToString("D3");

                case TagType.Text:
                    return this.textValuesPool[Random.Value.Next(0, TextValuesPoolCapacity)];

                default:
                    throw new ArgumentOutOfRangeException("type");
            }
        }

        private int GenerateBitValue()
        {
            return Random.Value.Next(0, 2);
        }

        private int GenerateIntegerValue(int min, int max)
        {
            return Random.Value.Next(min, max + 1);
        }

        private string GenerateTextValue(int size)
        {
            var builder = new StringBuilder();
            for (var i = 0; i < size; i++)
            {
                var ch = Convert.ToChar(Convert.ToInt32(Math.Floor((26 * Random.Value.NextDouble()) + 65)));
                builder.Append(ch);
            }

            return builder.ToString();
        }
    }
}